home *** CD-ROM | disk | FTP | other *** search
- /* $Revision Header *** Header built automatically - do not edit! ***********
- *
- * (C) Copyright 1991 by Torsten Jürgeleit
- *
- * Name .....: menus.c
- * Created ..: Thursday 19-Dec-91 18:02:58
- * Revision .: 2
- *
- * Date Author Comment
- * ========= ==================== ====================
- * 03-Jun-92 Torsten Jürgeleit subitems now indicated by `»',
- * alternate color for item texts,
- * now correct item width calculated
- * in init_menu()
- * 20-Apr-92 Torsten Jürgeleit Enforcer hit in init_menu -> *key
- * 19-Dec-91 Torsten Jürgeleit Created this file!
- *
- ****************************************************************************
- *
- * Menu support routines
- *
- * $Revision Header ********************************************************/
-
- /* Includes */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <intuition/intuition.h>
- #ifdef AZTEC_C
- #include <functions.h> /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
- #endif
- #include <libraries/memwatch.h> /* header file for memory debug link library (Fish 240) - AFTER functions.h */
- #include <string.h>
- #include "/render/render.h"
- #include "/language/language.h"
- #include "menus.h"
-
- /* Static prototypes */
-
- ULONG get_buffer_size(struct MenuList *ml);
- VOID get_item_text_pens(struct MenuList *ml);
- BOOL init_menu(struct MenuList *ml);
- USHORT intui_text_length(BYTE *text, struct TextAttr *ta);
- VOID equal_select_box_width(struct MenuItem *item);
-
- /* Static pragmas */
-
- #pragma regcall(get_buffer_size(a0))
- #pragma regcall(get_item_text_pens(a0))
- #pragma regcall(init_menu(a0))
- #pragma regcall(intui_text_length(a0,a1))
- #pragma regcall(equal_select_box_width(a0))
-
- /* Create menu list */
-
- struct MenuList *
- create_menu(struct RenderInfo *ri, struct Window *win,
- struct MenuData *md, struct TextAttr *ta, BYTE **language_text_array)
- {
- if (ri && ri->ri_ID == ISUP_ID && win && md) {
- struct MenuList *ml;
-
- if (ml = AllocMem((LONG)sizeof(struct MenuList),
- (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
- struct TextFont *tf;
-
- /* Init menu list struct */
- ml->ml_RenderInfo = ri;
- ml->ml_Window = win; /* needed for colors !!! */
- ml->ml_Data = md;
- ml->ml_TextAttr = ta;
- ml->ml_LanguageTextArray = language_text_array;
- ml->ml_Flags = 0;
- ml->ml_ID = ISUP_ID;
-
- /* Get font for menu texts */
- if (ta) {
- tf = OpenFont(ta);
- } else {
- tf = ri->ri_TextFont;
- }
- if (ml->ml_TextFont = tf) {
- if (ml->ml_BufferSize = get_buffer_size(ml)) {
- if (ml->ml_Buffer = AllocMem(ml->ml_BufferSize,
- (LONG)MEMF_PUBLIC | MEMF_CLEAR)) {
- get_item_text_pens(ml);
- if (init_menu(ml) == TRUE) {
- return(ml);
- }
- FreeMem(ml->ml_Buffer, ml->ml_BufferSize);
- }
- }
- if (ta) {
- CloseFont(tf);
- }
- }
- FreeMem(ml, (LONG)sizeof(struct MenuList));
- }
- }
- return(NULL);
- }
- /* Attach menu list to given window */
-
- VOID
- attach_menu(struct Window *win, struct MenuList *ml)
- {
- if (win && ml && ml->ml_ID == ISUP_ID) {
-
- /* Remove menu strip from old window if any and attach it to new one */
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- ClearMenuStrip(ml->ml_Window);
- }
- SetMenuStrip(win, (struct Menu *)ml->ml_Buffer);
- ml->ml_Window = win;
- ml->ml_Flags |= MENU_LIST_FLAG_ATTACHED;
- }
- }
- /* Return menu item address */
-
- struct MenuItem *
- menu_item_address(struct MenuList *ml, USHORT menu_num)
- {
- struct MenuItem *mi = NULL;
-
- if (ml && ml->ml_ID == ISUP_ID) {
- mi = ItemAddress((struct Menu *)ml->ml_Buffer, (LONG)menu_num);
- }
- return(mi);
- }
- /* Remove menu list from window currently attached to */
-
- struct Window *
- remove_menu(struct MenuList *ml)
- {
- struct Window *win = NULL;
-
- if (ml && ml->ml_ID == ISUP_ID) {
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- win = ml->ml_Window;
- ClearMenuStrip(win);
- ml->ml_Flags &= ~MENU_LIST_FLAG_ATTACHED;
- }
- }
- return(win);
- }
- /* Free menu */
-
- VOID
- free_menu(struct MenuList *ml)
- {
- if (ml && ml->ml_ID == ISUP_ID) {
- if (ml->ml_Flags & MENU_LIST_FLAG_ATTACHED) {
- ClearMenuStrip(ml->ml_Window);
- }
- if (ml->ml_TextAttr) {
- CloseFont(ml->ml_TextFont);
- }
- FreeMem(ml->ml_Buffer, ml->ml_BufferSize);
- FreeMem(ml, (LONG)sizeof(struct MenuList));
- }
- }
- /* Get buffer size for menus, items and intui texts */
-
- STATIC ULONG
- get_buffer_size(struct MenuList *ml)
- {
- struct MenuData *md = ml->ml_Data;
- ULONG buffer_size = 0;
-
- if (md->md_Type != INTUISUP_DATA_END &&
- md->md_Type == MENU_DATA_TYPE_TITLE) {
- USHORT menus = 0, items = 0, subitem_texts = 0;
- BOOL error = FALSE, subitem = FALSE;
-
- do {
- switch (md++->md_Type) {
- case MENU_DATA_TYPE_TITLE :
- menus++;
- subitem = FALSE;
- break;
-
- case MENU_DATA_TYPE_ITEM :
- items++;
- subitem = FALSE;
- break;
-
- case MENU_DATA_TYPE_SUBITEM :
- items++;
-
- /* If first subitem then add text with `»' to previous item */
- if (subitem == FALSE) {
- subitem_texts++;
- subitem = TRUE;
- }
- break;
-
- default :
- error = TRUE;
- break;
- }
- } while (error == FALSE && md->md_Type != INTUISUP_DATA_END &&
- md->md_Type <= MAX_MENU_DATA_TYPE);
- if (error == FALSE && menus && items) {
- buffer_size = menus * sizeof(struct Menu) + items *
- (sizeof(struct MenuItem) + sizeof(struct IntuiText)) +
- subitem_texts * sizeof(struct IntuiText);
- }
- }
- return(buffer_size);
- }
- /* Get two different text pens for items */
-
- STATIC VOID
- get_item_text_pens(struct MenuList *ml)
- {
- struct RenderInfo *ri = ml->ml_RenderInfo;
- SHORT num_colors;
-
- if ((num_colors = 1 << ri->ri_ScreenDepth) > MAX_RENDER_COLORS) {
- num_colors = MAX_RENDER_COLORS;
- }
- if (num_colors < 3) {
-
- /* Set render pens for monochrome screen */
- if (ml->ml_Window->BlockPen) {
- ml->ml_TextPen1 = 0;
- ml->ml_TextPen2 = 0;
- } else {
- ml->ml_TextPen1 = 1;
- ml->ml_TextPen2 = 1;
- }
- } else {
- struct ColorMap *cmap;
- SHORT i, max_diff, back_color, colors[MAX_RENDER_COLORS],
- pens[MAX_RENDER_COLORS];
-
- /* Get current screen colors */
- Forbid();
- cmap = ml->ml_Window->WScreen->ViewPort.ColorMap;
- for (i = 0; i < num_colors; i++) {
- colors[i] = GetRGB4(cmap, (LONG)i);
- pens[i] = i;
- }
- Permit();
-
- /* Save normal background color */
- back_color = colors[ml->ml_Window->BlockPen];
-
- /* Set text pen 1 - search color with greatest `difference' to backgound color */
- for (i = 0, max_diff = 0; i < num_colors; i++) {
- SHORT diff;
-
- if ((diff = calc_color_difference(colors[i], back_color)) >
- max_diff) {
- max_diff = diff;
- ml->ml_TextPen1 = pens[i];
- }
- }
-
- /* Set text pen 2 - search color with 2nd greatest `difference' to backgound color */
- for (i = 0, max_diff = 0; i < num_colors; i++) {
- SHORT diff;
-
- if ((diff = calc_color_difference(colors[i], back_color)) >
- max_diff && pens[i] != ri->ri_TextPen1) {
- max_diff = diff;
- ml->ml_TextPen2 = pens[i];
- }
- }
- }
- }
- /* Initialize menu from menu list */
-
- STATIC BOOL
- init_menu(struct MenuList *ml)
- {
- struct RenderInfo *ri = ml->ml_RenderInfo;
- struct TextFont *menu_tf = ri->ri_TextFont, *item_tf = ml->ml_TextFont;
- struct TextAttr *menu_ta = &ri->ri_TextAttr, *item_ta = ml->ml_TextAttr;
- struct MenuData *md;
- struct Menu *last_menu, *menu = NULL; /* MUST be defined OUT of for loop */
- struct MenuItem *last_item, *last_subitem, *item = NULL; /* MUST be defined OUT of for loop */
- BYTE *buffer = ml->ml_Buffer;
- SHORT item_ypos, subitem_xpos, subitem_ypos; /* MUST be defined OUT of for loop */
- BOOL success = FALSE, error = FALSE, subitem_flag = FALSE;
-
- /* Init menus and items */
- for (md = ml->ml_Data; md->md_Type != INTUISUP_DATA_END &&
- md->md_Type <= MAX_MENU_DATA_TYPE; md++) {
- struct IntuiText *itext;
- USHORT type, flags;
- BYTE *name, *key;
-
- /* Get data from menu data structure */
- type = md->md_Type;
- flags = md->md_Flags;
- name = get_language_text(md->md_Text, ml->ml_LanguageTextArray);
- key = (!md->md_CommandKey ? NULL :
- get_language_text(md->md_CommandKey, ml->ml_LanguageTextArray));
-
- /* Init structures according to data type */
- switch (type) {
- case MENU_DATA_TYPE_TITLE :
-
- /* Prepare last menu and subitem list */
- if (menu) {
- equal_select_box_width(menu->FirstItem);
- }
- if (subitem_flag == TRUE) {
- equal_select_box_width(last_item->SubItem);
- }
-
- /* Init data for new menu */
- item = NULL;
- last_item = NULL;
- last_subitem = NULL;
- item_ypos = 0;
- subitem_flag = FALSE;
- last_menu = menu;
- menu = (struct Menu *)buffer;
- buffer += sizeof(struct Menu);
-
- /* Init new menu */
- if (last_menu) {
-
- /* If this isn't the first menu then connect it to last menu */
- last_menu->NextMenu = menu;
- menu->LeftEdge = last_menu->LeftEdge + last_menu->Width +
- menu_tf->tf_XSize;
- } else {
- menu->LeftEdge = 5;
- }
- menu->Width = intui_text_length(name, menu_ta) +
- menu_tf->tf_XSize;
- menu->Height = menu_tf->tf_YSize;
- menu->Flags = MIDRAWN | (flags & MENU_DATA_FLAG_DISABLED ?
- 0 : MENUENABLED);
- menu->MenuName = name;
- menu->FirstItem = (struct MenuItem *)buffer;
- break;
-
- case MENU_DATA_TYPE_ITEM :
- case MENU_DATA_TYPE_SUBITEM :
-
- /* Init item data */
- if (subitem_flag == TRUE) {
- last_subitem = item;
- } else {
- last_item = item;
- }
- item = (struct MenuItem *)buffer;
- itext = (struct IntuiText *)(item + 1);
- buffer += sizeof(struct MenuItem) + sizeof(struct IntuiText);
-
- /* Init intui text */
- itext->LeftEdge = (flags & MENU_DATA_FLAG_ATTRIBUTE ?
- CHECKWIDTH : 0);
- itext->TopEdge = 1;
- itext->FrontPen = (flags & MENU_DATA_FLAG_TEXT_COLOR2 ?
- ml->ml_TextPen2 : ml->ml_TextPen1);
- itext->DrawMode = JAM1;
- itext->ITextFont = item_ta;
- itext->IText = (UBYTE *)name;
-
- /* Init menu item */
- item->Width = intui_text_length(name, item_ta) +
- (key ? COMMWIDTH + 2 * item_tf->tf_XSize : 0) +
- (flags & MENU_DATA_FLAG_ATTRIBUTE ? CHECKWIDTH : 0);
- item->Height = item_tf->tf_YSize + 1;
- item->Flags = ITEMTEXT | (key ? COMMSEQ : 0) |
- (flags & MENU_DATA_FLAG_DISABLED ? 0 : ITEMENABLED) |
- (flags & MENU_DATA_FLAG_HIGH_NONE ? HIGHNONE :
- (flags & MENU_DATA_FLAG_HIGH_BOX ? HIGHBOX : HIGHCOMP)) |
- (flags & MENU_DATA_FLAG_ATTRIBUTE ? CHECKIT : 0) |
- (flags & MENU_DATA_FLAG_SELECTED ? CHECKED : 0);
- item->MutualExclude = md->md_MutualExclude;
- item->ItemFill = (APTR)itext;
- item->SelectFill = (APTR)itext;
- item->Command = (key ? *key : 0);
- item->NextSelect = MENUNULL;
-
- /* Insert empty line before item ? */
- if (flags & MENU_DATA_FLAG_EMPTY_LINE) {
- if (type == MENU_DATA_TYPE_SUBITEM) {
- subitem_ypos += item->Height;
- } else {
- item_ypos += item->Height;
- }
- }
- if (type == MENU_DATA_TYPE_SUBITEM) {
- if (subitem_flag == TRUE) {
- last_subitem->NextItem = item;
- } else {
- if (!last_item) {
- error = TRUE; /* no menu item to attach subitem */
- break;
- } else {
- struct IntuiText *new_itext,
- *last_itext = (struct IntuiText *)
- last_item->ItemFill;
- /* Create intui text for sub item indicator `»' */
- new_itext = (struct IntuiText *)buffer;
- buffer += sizeof(struct IntuiText);
- new_itext->TopEdge = last_itext->TopEdge;
- new_itext->FrontPen = last_itext->FrontPen;
- new_itext->DrawMode = JAM1;
- new_itext->ITextFont = item_ta;
- new_itext->IText = (UBYTE *)"»";
- last_itext->NextText = new_itext;
-
- /* Connect sub item to menu item */
- last_item->Width += intui_text_length((BYTE *)
- new_itext->IText, item_ta) + item_tf->tf_XSize;
- last_item->SubItem = item;
- subitem_xpos = intui_text_length((BYTE *)
- last_itext->IText, item_ta) +
- (last_item->Flags & CHECKIT ? CHECKWIDTH : 0);
- subitem_ypos = 0;
- subitem_flag = TRUE;
- }
- }
- item->LeftEdge = subitem_xpos;
- item->TopEdge = subitem_ypos;
- subitem_ypos += item->Height;
- } else {
- if (last_item) {
- last_item->NextItem = item;
- }
- item->TopEdge = item_ypos;
- item_ypos += item->Height;
- if (subitem_flag == TRUE) {
-
- /* Prepare last subitem list */
- equal_select_box_width(last_item->SubItem);
- subitem_flag = FALSE;
- }
- }
- break;
- }
- }
- if (error == FALSE && item) {
-
- /* Prepare current menu and subitem list */
- equal_select_box_width(menu->FirstItem);
- if (subitem_flag == TRUE) {
- equal_select_box_width(last_item->SubItem);
- }
- success = TRUE;
- }
- return(success);
- }
- /* Calc text length in pixels */
-
- STATIC USHORT
- intui_text_length(BYTE *text, struct TextAttr *ta)
- {
- struct IntuiText itext;
-
- /* Init dummy intui text and return text length */
- itext.IText = (UBYTE *)text;
- itext.ITextFont = ta;
- return(IntuiTextLength(&itext));
- }
- /* Set equal select box width for given menu item list */
-
- STATIC VOID
- equal_select_box_width(struct MenuItem *item)
- {
- struct MenuItem *save_item = item;
- ULONG max_width = 0;
-
- /* Search max width */
- do {
- if (item->Width > max_width) {
- max_width = item->Width;
- }
- } while (item = item->NextItem);
-
- /* Set max width */
- item = save_item;
- do {
- item->Width = max_width;
-
- /* If subitem then calc left edge of subitem indicator `»' */
- if (item->SubItem) {
- struct IntuiText *itext = ((struct IntuiText *)
- item->ItemFill)->NextText;
- itext->LeftEdge = max_width - intui_text_length((BYTE *)
- itext->IText, itext->ITextFont);
- }
- } while (item = item->NextItem);
- }
-